/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package l1j.server.server.serverpackets;

import static l1j.server.server.model.skill.L1SkillId.*;

import java.util.Map;
import java.util.logging.Logger;

import l1j.server.server.Opcodes;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.utils.ByteArrayUtil;
import l1j.server.server.utils.IntRange;
import l1j.server.server.utils.collections.Maps;

//activeSpells(L1PcInstance pc)
//data의 각 치에 100을 넣어 봐 아이콘이 나올지 어떨지 테스트했다
//대부분의 스킬은, 값의 4배의 초수가 남은 시간으로서 표시된다
//일부의 스킬은 16배의 초수가 표시되기 (위해)때문에, 그 스킬에 대해서는 계수 16으로 기재했다
//0:묵상
//1:None
//2:None
//3:디크리스웨이트(계수 16)
//4:디케이포션
//5:앱설루트 바리어
//6:침묵
//7:베놈레지스트
//8:위크네스
//9:디지즈
//10-16:None
//17:드레스이베이젼
//18:바서카
//19:네이챠즈탓치
//20:윈드산크루
//21:erase 매직?
//22:카운터 밀러?
//23:아디쇼나르파이아(계수 16)
//24:일렉트로닉 멘탈 폴 다운
//25:None
//26:일렉트로닉 멘탈 파이어
//27:None
//28:기색을 지워 monster들을 알아차려지지 않게 합니다(? )
//29:None
//30:스트라이카게일
//31:소우르오브후레임
//32:포르트워타
//33-40:None
//44:스펠 파워가 상승합니다
//45-51:None
//52:집중(계수 16)
//53:인 사이트(계수 16)
//54:패닉(계수 16)
//55:모타르보디
//56:호라오브데스
//57:피아
//58:페이시스
//59:가이드 브레이크
//60:드래곤 스킨(계수 16)
//61:이동 속도가 빨라집니다
//62-101:None
//102-103:?

public class S_ActiveSpells extends ServerBasePacket {
	private byte[] _byte = null;
	private static final Map<Integer, ActiveSkill> _indexes = Maps.newHashMap();
	private static Logger _log = Logger.getLogger(S_ActiveSpells.class
			.getName());

	private static class ActiveSkill {
		public final int id;
		public final int timeCoefficient;

		public ActiveSkill(int skillId, int timeCoefficient) {
			this.id = skillId;
			this.timeCoefficient = timeCoefficient;
		}
	}

	private static void addIndex(int skillIndex, int skillId) {
		addIndex(skillIndex, skillId, 4);
	}

	private static void addIndex(int skillIndex, int skillId,
			int timeCoefficient) {
		ActiveSkill skill = new ActiveSkill(skillId, timeCoefficient);
		_indexes.put(skillIndex, skill);
	}

	static {
		// スキルインデックス定義
		addIndex(0, MEDITATION);
		addIndex(3, DECREASE_WEIGHT, 16);
		addIndex(4, DECAY_POTION);
		addIndex(5, ABSOLUTE_BARRIER);
		addIndex(6, SILENCE);
		addIndex(7, VENOM_RESIST);
		addIndex(8, WEAKNESS);
		addIndex(9, DISEASE);
		addIndex(17, DRESS_EVASION);
		addIndex(18, BERSERKERS);
		addIndex(19, NATURES_TOUCH);
		// addIndex(20, WIND_SHACKLE); // ここで送っても攻撃速度は下がらない
		addIndex(21, ERASE_MAGIC);
		addIndex(22, COUNTER_MIRROR);
		addIndex(23, ADDITIONAL_FIRE, 16);
		addIndex(24, ELEMENTAL_FALL_DOWN);
		addIndex(26, ELEMENTAL_FIRE);
		// addIndex(28, /* 気配を消しモンスターたちに気付かれないようにします(?) */);
		addIndex(30, STRIKER_GALE);
		addIndex(31, SOUL_OF_FLAME);
		addIndex(32, POLLUTE_WATER);
		// addIndex(44, /* スペルパワーが上昇します */);
		addIndex(52, CONCENTRATION, 16);
		addIndex(53, INSIGHT, 16);
		addIndex(54, PANIC, 16); // TODO implement
		addIndex(55, MORTAL_BODY);
		addIndex(56, HORROR_OF_DEATH);
		// addIndex(57, /*フィアー*/);
		addIndex(58, PATIENCE);
		addIndex(59, GUARD_BRAKE);
		addIndex(60, DRAGON_SKIN, 16);
		// addIndex(61, /*移動速度が速くなります*/);
	}

	public S_ActiveSpells(L1PcInstance pc) {
		buildPacket(pc);
	}

	private String makeOverflowMessage(L1PcInstance pc, ActiveSkill skill) {
		StringBuilder result = new StringBuilder();
		result.append("스킬의 효과 시간이 송신 가능한 범위를 넘고 있습니다. \n");
		result.append("Hint: 효과 시간을 독자적으로 설정해 있는 경우는, 한계 효과 시간 이하로 설정해 주세요. \n");
		String detail = String.format("플레이어명: %s, 스킬 ID: %d\n", pc.getName(),
				skill.id);
		int time = pc.getSkillEffectTimeSec(skill.id);
		String detail2 = String.format("현재의 효과 시간: %d 초, 한계 효과 시간: %d 초이하", time,
				255 * skill.timeCoefficient);
		result.append(detail);
		result.append(detail2);
		return result.toString();
	}

	private byte getTime(L1PcInstance pc, int skillIndex) {
		ActiveSkill skill = _indexes.get(skillIndex);
		if (skill == null) {
			return 0;
		}
		int time = pc.getSkillEffectTimeSec(skill.id);
		if (time == -1) {
			return 0;
		}
		time /= skill.timeCoefficient;
		if (!IntRange.includes(time, 0, 255)) {
			// 오버플로우 했다.
			_log.warning(makeOverflowMessage(pc, skill));
			time = 255;
		}
		return (byte) time;
	}

	private byte[] activeSpells(L1PcInstance pc) {
		final int SIZE_OF_SPELLS = 104;
		byte[] data = new byte[SIZE_OF_SPELLS];
		for (int i = 0; i < SIZE_OF_SPELLS; i++) {
			data[i] = getTime(pc, i);
		}
		// 용도 불명
		int unixTime = (int) (System.currentTimeMillis() / 1000);
		ByteArrayUtil.writeInteger(unixTime, data, 72);
		return data;
	}

	private void buildPacket(L1PcInstance pc) {
		writeC(Opcodes.S_OPCODE_ACTIVESPELLS);
		writeC(0x14);
		writeBytes(activeSpells(pc));
		_byte = _bao.toByteArray();
	}

	@Override
	public byte[] getContent() {
		return _byte;
	}
}